home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / MacDP 1.3 / JFIF-PICT.c next >
Encoding:
C/C++ Source or Header  |  1997-03-31  |  21.5 KB  |  992 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        JPEGtoPICT.c
  3.  
  4.     Written by:    Mark Krueger, Apple Computer, Inc.
  5.  
  6.     Contains:    Converts JPEG interchange files to JPEG PICT files, which can be used by any application.
  7.     
  8.     
  9.                 The JPEG File  Interchange Format ( JFIF) is a cross platform standard file format for
  10.                 storing JPEG compressed image files. This application shows you how you can easily convert
  11.                 these to QuickTime PICT format, or vice-verse. 
  12.                 
  13.                 You can use this in your application to open JFIF files directly or put a user interface 
  14.                 ( Drag and Drop would be cool ) on it to make a conversion program ). When files are to 
  15.                 be used on the Mac it is best to keep them in QTPict format so they can be easily copied
  16.                 and pasted, but JFIF format is useful for transfering data to other platforms that cannot
  17.                 use PICT formated JPEG images. 
  18.                 
  19.                 NOTE: the PICT to JFIF format translator is incomplete in that it only converts PICT
  20.                 files which are already in QuickTIme JPEG format and it does not handle banded JPEG
  21.                 Picts ( which may be commonly created by QuickTime applications which call 
  22.                 CompressPictureFile in low memory conditions or which create their own banded picts)
  23.                 To fully handle these images, the individual bands would have to be converted into a 
  24.                 single JPEG stream when put into JFIF format, and this code does not show you how
  25.                 to do that. 
  26.             
  27.     Modifications: November 19, 1994 by SPDsoft for MacDP 1.0
  28.  
  29.  
  30. */
  31.  
  32. #ifndef __QUICKDRAW__
  33.     /* if MacHeaders has been included, __QUICKDRAW__ should be defined */
  34.  
  35. #include    <Types.h>
  36. #include    <Files.h>
  37. #include    <Quickdraw.h>
  38. #include    <Packages.h>
  39. #include    <Memory.h>
  40. #include    <Fonts.h>
  41. #include    <Events.h>
  42. #include    <OSUtils.h>
  43. #include    <ToolUtils.h>
  44. #include    <Menus.h>
  45. #include    <Dialogs.h>
  46. #include    <stdio.h>
  47. #include    <Errors.h>
  48. #include    <string.h>
  49. #include    <StandardFile.h>
  50. #endif /* MacHeaders */
  51.  
  52. #include    <GestaltEqu.h>
  53. #include    <ImageCompression.h>
  54.  
  55. /************************************************
  56.  *
  57.  *    Function prototypes.
  58.  *
  59.  ************************************************/
  60.  
  61.  
  62. char *
  63. MarkerDetect(char *data,short *width,short *height,long *hRes,long *vRes,short *depth);
  64.  
  65. void 
  66. SwallowHuffTable(char *data);
  67.  
  68. void 
  69. SwallowQuantTable(char *data);
  70.  
  71. ImageDescriptionHandle
  72. ScanJPEG(short originalFile,Ptr *data,OpenCPicParams *pictureHeader);
  73.  
  74. PicHandle
  75. ConvertFromJFIF(StringPtr name,short originalFile, CWindowPtr window );
  76.  
  77. PicHandle
  78. ConvertFromPict(StringPtr name,short originalFile, CWindowPtr w);
  79.  
  80. pascal void
  81. StdPixExtract(PixMap *src,Rect *srcRect,MatrixRecord matrix,short mode,RgnHandle mask,PixMap *matte,
  82.     Rect *matteRect,short flags);
  83.     
  84. pascal void GetPICTData ( Ptr dataPtr, short byteCount);
  85.  
  86.  
  87. /************************************************
  88.  *
  89.  *    Convert a JFIF file to a PICT file.
  90.  *
  91.  ************************************************/
  92.  
  93.  
  94.  
  95. PicHandle
  96. ConvertFromJFIF(StringPtr name,short originalFile, CWindowPtr window )
  97. {
  98. #pragma unused(name)
  99. #pragma unused(window)
  100.  
  101.     OSErr    result = 0;
  102.     short compressedFile = 0;
  103.     OpenCPicParams    header;
  104. //    Str31        newName;
  105. //    long        l;
  106. //    short        i;
  107.     char        zero=0;
  108.     MatrixRecord matrix;
  109.  
  110.     Ptr            data = nil;
  111.     ImageDescriptionHandle    desc = nil;
  112.     PicHandle    originalPicture = nil;
  113.  
  114.     
  115.     /************************************************
  116.      *
  117.      *    Extract the JPEG data if possible and create Image Description.
  118.      *
  119.      ************************************************/
  120.  
  121.     if ( (desc=ScanJPEG(originalFile,&data,&header)) == 0 ) {
  122.         result = -50;
  123.         goto done;
  124.     }
  125.  
  126.     originalPicture = OpenCPicture(&header);
  127.         
  128.         
  129.     /************************************************
  130.      *
  131.      * we have to use the FDecompressImage call to make sure that the accuracy
  132.      * param gets set to highQuality which ensures a better quality decode
  133.      * and real dithering when going to 8-bit screens.
  134.      *
  135.      ************************************************/
  136.         
  137.         
  138.     SetIdentityMatrix(&matrix);
  139.     
  140. /*SysBeep(1);    */
  141.     if ( (result=FDecompressImage(data,desc,((CGrafPtr)qd.thePort)->portPixMap,
  142.             &header.srcRect,&matrix,ditherCopy,(RgnHandle)nil,
  143.             (PixMapHandle)nil,(Rect *)nil,codecHighQuality,anyCodec,0,
  144.             (ICMDataProcRecordPtr)nil,(ICMProgressProcRecordPtr)nil)) ){
  145.         ClosePicture();
  146.         KillPicture((PicHandle)originalPicture);
  147.         originalPicture = nil;
  148.         goto done;
  149.     }
  150. /*SysBeep(1);    */
  151.  
  152.     ClosePicture();
  153.     
  154.     if ( GetHandleSize((Handle)originalPicture) == sizeof(Picture) ) {
  155.         KillPicture((PicHandle)originalPicture);
  156.         originalPicture = nil;
  157.         goto done;
  158.     }
  159.  
  160.  
  161. done:    
  162.     FSClose(originalFile);
  163.  
  164. /*    if ( originalPicture )*/
  165. /*        KillPicture(originalPicture);*/
  166.  
  167.     if ( data )
  168.         DisposPtr(data);
  169.     if ( desc ) 
  170.         DisposHandle((Handle)desc);
  171.  
  172.     return originalPicture;
  173. }
  174.  
  175.  
  176. /************************************************
  177.  
  178.     Scan a file for valid JPEG data, and fill in a picture header and ImageDescription
  179.     for it.
  180.  
  181. *************************************************/
  182.  
  183. ImageDescriptionHandle
  184. ScanJPEG(short originalFile,Ptr *data,OpenCPicParams *pictureHeader)
  185.  
  186. {
  187.     short w,h;
  188.     ImageDescriptionHandle desc;
  189.     long    l;
  190.     char    *bitStream,*scanData,*buffer;
  191.     long    hRes = 72L<<16,vRes = 72L<<16;
  192.     short    depth = 32;
  193.     
  194.     GetEOF(originalFile,&l);
  195.     if ( (buffer= NewPtr(l)) == nil ) {
  196.         return(0);
  197.     }
  198.     FSRead(originalFile,&l,buffer);
  199.     bitStream = buffer;
  200.     
  201.     if ( (desc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription))) == nil ) {
  202.         return(0);
  203.     }
  204.     if ( (scanData=MarkerDetect(bitStream,&w,&h,&hRes,&vRes,&depth)) == 0 ) {
  205.         return(0);
  206.     }
  207.     (*desc)->idSize = sizeof(ImageDescription);
  208.     (*desc)->width = w;
  209.     (*desc)->height = h;
  210.     (*desc)->temporalQuality = 0;
  211.     (*desc)->spatialQuality = codecNormalQuality;
  212.     (*desc)->dataSize = l;
  213.     (*desc)->cType = 'jpeg';
  214.     (*desc)->version = 0;
  215.     (*desc)->revisionLevel = 0;
  216.     (*desc)->vendor = 0;
  217.     (*desc)->hRes = hRes;
  218.     (*desc)->vRes = vRes;
  219.     (*desc)->depth = depth;
  220.     (*desc)->clutID = -1;
  221.     BlockMove("\pPhoto",(*desc)->name,6);
  222.     SetRect(&pictureHeader->srcRect,0,0,w,h);
  223.     pictureHeader->version = -2;
  224.     pictureHeader->reserved1 = 0;
  225.     pictureHeader->reserved2 = 0;
  226.     pictureHeader->hRes = hRes;
  227.     pictureHeader->vRes = vRes;
  228.     *data = bitStream;
  229.     return(desc);
  230. }
  231.  
  232.  
  233.  
  234. /**********************************************************************
  235.  
  236.     JPEG specific stuff.
  237.     
  238. ***********************************************************************/
  239.  
  240. /*
  241.  
  242.     JPEG Marker code definitions.
  243.     
  244. */
  245.  
  246. #define    MARKER_PREFIX    0xff
  247. #define    MARKER_SOI    0xd8        /* start of image */
  248. #define    MARKER_SOF    0xc0        /* start of frame */
  249. #define    MARKER_DHT    0xc4        /* define Huffman table */
  250. #define    MARKER_EOI    0xd9        /* end of image */
  251. #define    MARKER_SOS    0xda        /* start of scan */
  252. #define    MARKER_DQT    0xdb        /* define quantization tables */
  253. #define    MARKER_DNL    0xdc        /* define quantization tables */
  254. #define    MARKER_DRI    0xdd        /* define Huffman table */
  255. #define    MARKER_COM    0xfe        /* comment */
  256. #define MARKER_APP0    0xe0        
  257.  
  258.  
  259. /**********************************************************************
  260.  
  261.     Read the quantization table from the JPEG bitstream.
  262.     
  263. ***********************************************************************/
  264.  
  265. void 
  266. SwallowQuantTable(char *data)
  267. {
  268.     long    i;
  269.     long    length,pm,nm;
  270.  
  271.     length = *(short *)data;            /* read length */
  272.     length -= 2;
  273.     data += 2;
  274.     while ( length ) {
  275.         nm= *data++;                    /* read precision and number */
  276.         pm = nm>>4;    
  277.         nm &= 0xf;
  278.         length--;
  279.         if ( pm ) {
  280.             for(i=0;i<64;i++) {
  281.                 length -= 2;
  282.                 data += 2;
  283.             }
  284.         } else {
  285.             for(i=0;i<64;i++) {
  286.                 length--;
  287.                 data++;
  288.             }
  289.         }
  290.     }    
  291. }
  292.  
  293. /**********************************************************************
  294.  
  295.     Read the huffman table from the JPEG bitstream.
  296.     
  297. ***********************************************************************/
  298.  
  299. void 
  300. SwallowHuffTable(char *data)
  301. {
  302.     short    i,tc,id;
  303.     long    length;
  304.     
  305.     unsigned char    bin[17];
  306.     unsigned char    val[256];
  307.  
  308.     bin[0] = 0;
  309.     length = *(short *)data;            /* read length */
  310.     data += 2;
  311.     length -= 2;
  312.     while ( length ) {
  313.         id=*data++;                /* read id */
  314.         length--;
  315.         if ( id != 0 && id != 1 && id != 0x10 && id != 0x11) {
  316.             return;
  317.         }
  318.         tc = 0;
  319.         for(i=0;i<16;i++) {
  320.             length--;
  321.             tc += (bin[i+1] = *data++);
  322.         }
  323.         for (i=0; i < tc; i++ ) {
  324.             length--;
  325.             val[i] = *data++;
  326.         }
  327.     }
  328. }
  329.     
  330.     
  331.     
  332. /**********************************************************************
  333.  
  334.     Scan the JPEG stream for the proper markers and fill in the image parameters
  335.     
  336.     returns nil if it cant comprehend the data, otherwise a pointer to the start
  337.     of the JPEG data.
  338.     
  339.     
  340.     It does a cursory check on the JPEG data to see if it's reasonable.
  341.     Check out the ISO JPEG spec if you really want to know what's going on here.
  342.     
  343. ***********************************************************************/
  344.  
  345. char *
  346. MarkerDetect(char *data,short *width,short *height,long *hRes,long *vRes,short *depth)
  347. {
  348.     short    frame_field_length;
  349.     short    data_precision;
  350.     short    scan_field_length;
  351.     short    number_component,scan_components;
  352.     short    c1,hv1,q1,c2,hv2,q2,c3,hv3,q3;
  353.     short    dac_t1, dac_t2, dac_t3;
  354.     unsigned char    c;
  355.     short    qtabledefn;
  356.     short    htabledefn;
  357.     short    status;
  358.     short    length;
  359.     short    i;
  360.     
  361.     c = *data++;
  362.     qtabledefn = 0;
  363.     htabledefn = 0;
  364.     status = 0;
  365.     while (c != (unsigned char)MARKER_SOS) {
  366.         while (c != (unsigned char)MARKER_PREFIX)
  367.             c = *data++;                        /* looking for marker prefix bytes */
  368.         while (c == (unsigned char)MARKER_PREFIX)
  369.             c = *data++;                        /* (multiple?) marker prefix bytes */
  370.         if (c == 0)
  371.             continue;                                    /* 0 is never a marker code */
  372.  
  373.         if (c == (unsigned char)MARKER_SOF) {
  374.  
  375.             frame_field_length = *(short *)data;
  376.             data += 2;
  377.             data_precision = *data++;
  378.             
  379.             if ( data_precision != 8 ) { 
  380.                 status = 2;
  381.             }
  382.  
  383.             *height = *(short *)data;
  384.             data += 2;
  385.             *width = *(short *)data;
  386.             data += 2;
  387.                         
  388.             number_component = *data++;
  389.             
  390.             switch ( number_component  ) {
  391.             case 3:
  392.                 c1 = *data++;
  393.                 hv1 = *data++;
  394.                 q1 = *data++;
  395.                 c2 = *data++;
  396.                 hv2 = *data++;
  397.                 q2 = *data++;
  398.                 c3 = *data++;
  399.                 hv3 = *data++;
  400.                 q3 = *data++;
  401.                 *depth = 32;
  402.                 break;
  403.             case 1:        
  404.                 c1 = *data++;
  405.                 hv1 = *data++;
  406.                 q1 = *data++;
  407.                 *depth = 40;
  408.                 break;
  409.             default:
  410.                 status = 3;
  411.                 break;
  412.             }
  413.             continue;
  414.         }
  415.     
  416.         if (c == (unsigned char)MARKER_SOS) {
  417.             short tn;
  418.             scan_field_length = *(short *)data;
  419.             data += 2;
  420.             scan_components = *data++;
  421.             for ( i=0; i < scan_components; i++ ) {
  422.                 unsigned char cn,dac_t;
  423.                 
  424.                 cn = *data++;
  425.                 dac_t = *data++;
  426.                 if ( cn == c1 ) {
  427.                     dac_t1 = dac_t;
  428.                 } else if ( cn == c2 ) {
  429.                     dac_t2 = dac_t;
  430.                 } else if ( cn == c3 ) {
  431.                     dac_t3 = dac_t;
  432.                 } else {    
  433.                     status = 29;
  434.                     break;
  435.                 }
  436.             }
  437. #ifdef strict_version_check                    
  438.             switch ( tn=(dac_t1 & 0xf) )  {
  439.             case 0:
  440.             case 1:
  441.                 break;
  442.             case 0xf:
  443.                 break;
  444.             default:
  445.                 status = 33;
  446.                 break;
  447.             }
  448.             switch (  tn=(dac_t2 & 0xf) )  {
  449.             case 0:
  450.             case 1:
  451.                 break;
  452.             case 0xf:
  453.                 break;
  454.             default:
  455.                 status = 33;
  456.                 break;
  457.             }
  458.             switch (  tn=(dac_t3 & 0xf) )  {
  459.             case 0:
  460.             case 1:
  461.                 break;
  462.             case 0xf:
  463.                 break;
  464.             default:
  465.                 status = 33;
  466.                 break;
  467.             }
  468.  
  469.  
  470.             /*  Initialize the DC tables */
  471.             
  472.             switch (  tn=dac_t1 & 0xf0 )  {
  473.             case 0:
  474.             case 0x10:
  475.                 break;
  476.             case 0xf0:
  477.                 break;
  478.             default:
  479.                 status = 34;
  480.                 break;
  481.             }
  482.             switch (  tn=dac_t2 & 0xf0 )  {
  483.             case 0:
  484.             case 0x10:
  485.                 break;
  486.             case 0xf0:
  487.                 break;
  488.             default:
  489.                 status = 34;
  490.                 break;
  491.             }
  492.             switch (  tn=dac_t3 & 0xf0 )  {
  493.             case 0:
  494.             case 0x10:
  495.                 break;
  496.             case 0xf0:
  497.                 break;
  498.             default:
  499.                 status = 34;
  500.                 break;
  501.             }
  502. #endif
  503.             if ( *data++ != 0 )  {
  504. //                status = 18;
  505.             }
  506.             if ( *data++ != 63 )  {
  507. //                status = 19;
  508.             }
  509.             if ( *data++ != 0 ) {
  510. //                status = 20;
  511.             }
  512.             if ( status )
  513.                 return(0);
  514.             else
  515.                 return(data);
  516.         }
  517.  
  518.         if (c == (unsigned char)MARKER_DQT) {
  519.             scan_field_length = *(short *)data;
  520.             SwallowQuantTable(data);
  521.             data += scan_field_length;
  522.             continue;
  523.         }
  524.         if (c == (unsigned char)MARKER_DHT) {
  525.             scan_field_length = *(short *)data;
  526.             SwallowHuffTable(data);
  527.             continue;
  528.         }
  529.         if (c == (unsigned char)MARKER_DRI) {
  530.             length = *(short *)data;            /* read length */
  531.             data += 2;
  532.             length = *(short *)data;            
  533.             data += 2;
  534.             continue;
  535.         }
  536.         if (c == (unsigned char)MARKER_DNL) {
  537.             length = *(short *)data;            /* read length */
  538.             data += 2;
  539.             length = *(short *)data;            
  540.             data += 2;
  541.             continue;
  542.         }
  543.         if (c >= (unsigned char)0xD0 && c <= (unsigned char)0xD7) {
  544.             continue;
  545.         }
  546.  
  547.         if (c == (unsigned char)MARKER_SOI || c == (unsigned char)MARKER_EOI)    /* image start, end marker */
  548.             continue;
  549.  
  550.         if ( (c >= (unsigned char)0xC1 && c <= (unsigned char)0xcF) || (c == (unsigned char)0xde) || (c == (unsigned char)0xdf) ) {
  551.             status = 12;
  552.             length = *(short *)data;            /* read length */
  553.             data += length;
  554.             continue;
  555.         }
  556.         if (c >= (unsigned char)MARKER_APP0 && c <= (unsigned char)0xEF) {
  557.             length = *(short *)data;            /* read length */
  558.             data += 2;
  559.             length -= 2;
  560.             if ( (c == (unsigned char)MARKER_APP0) && length > 5 ) { /* check for JFIF marker */
  561.                 char buf[5];
  562.                 buf[0] = *data++;
  563.                 buf[1] = *data++;
  564.                 buf[2] = *data++;
  565.                 buf[3] = *data++;
  566.                 buf[4] = *data++;
  567.                 length -= 5;
  568.                 
  569.                 if ( buf[0] == 'J' && buf[1] == 'F'  && buf[2] == 'I'  && buf[3] == 'F' ) {
  570.                     short    units;
  571.                     long    xres,yres;
  572.                     short    version;
  573.                     
  574.                     
  575.                     version = *(short *)data; data += 2;length -= 2;
  576.  
  577. #ifdef strict_version_check                    
  578.                     if ( version != 0x100 && version != 0x101 ) {
  579.                         status = 44;        // unknown JFIF version
  580.                         break;
  581.                     }
  582. #else
  583.                     if ( version < 0x100 ) {
  584.                         status = 44;        // unknown JFIF version
  585.                         break;
  586.                     }
  587. #endif                    
  588.                     units = *data++; length--;
  589.                     xres = *(short *)data; data += 2; length -= 2;
  590.                     yres = *(short *)data; data += 2; length -= 2;
  591.  
  592.                     switch ( units ) {
  593.                     case 0:            // no res, just aspect ratio
  594.                         *hRes = FixMul(72L<<16,xres<<16);
  595.                         *vRes = FixMul(72L<<16,yres<<16);
  596.                         break;
  597.                     case 1:            // dots per inch
  598.                         *hRes = xres<<16;
  599.                         *vRes = yres<<16;
  600.                         break;
  601.                     case 2:            // dots per centimeter (we convert to dpi )
  602.                         *hRes = FixMul(0x28a3d,xres<<16);
  603.                         *vRes = FixMul(0x28a3d,xres<<16);
  604.                         break;    
  605.                     default:
  606.                         break;
  607.                     }
  608.                     xres = *data++; length--;
  609.                     yres = *data++; length--;
  610.                     
  611.                     /* skip JFIF thumbnail */
  612.                     
  613.                     xres *= yres;
  614.                     data += xres*3; length -= xres*3;
  615.                     
  616.                     if (  length != 0 ) {
  617.                         status = 44;        // bad jfif marker
  618.                         break;
  619.                     }
  620.                 }
  621.             }
  622.             data += length;
  623.             continue;
  624.         }
  625.         if (c == (unsigned char)MARKER_COM) {
  626.             length = *(short *)data;            /* read length */
  627.             data += length;
  628.             continue;
  629.         }
  630.         if (c >= (unsigned char)0xf0 && c <= (unsigned char)0xfd) {
  631.             length = *(short *)data;            /* read length */
  632.             data += length;
  633.             continue;
  634.         }
  635.         if ( c == 0x1 )
  636.             continue;
  637.         if ( (c >= (unsigned char)0x2 && c <= (unsigned char)0xbF) ) {
  638.             length = *(short *)data;            /* read length */
  639.             status = 13;
  640.             data += length;
  641.             continue;
  642.         }
  643.     }
  644.     return(0);
  645. }
  646.  
  647.  
  648.  
  649.  
  650.  
  651. short extractionFile;
  652. OSErr extractionErr;
  653. extern short globalRef;
  654.  
  655. PicHandle
  656. ConvertFromPict(StringPtr name,short originalFile,CWindowPtr w)
  657. {
  658. #pragma unused(name)
  659.  
  660. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  661.     QDGetPicUPP GetPicUPP;
  662. #endif
  663.     CQDProcs    cprocs;
  664.     CQDProcsPtr savedprocs;
  665.     CGrafPtr    savePort;
  666.     OSErr        result = 0;
  667.     PicHandle    thePic = nil, OutPict = nil;
  668.     long        longCount,myEOF;
  669.     Rect        destRect;
  670.     long        hRes = 72L<<16,
  671.                 vRes = 72L<<16;
  672.  
  673.     OpenCPicParams    Header;
  674. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  675.     GetPicUPP = NewQDGetPicProc( &GetPICTData );
  676. #endif
  677.         
  678.     GetPort((GrafPtr *) &savePort);
  679.     SetPort((GrafPtr) w);
  680.     globalRef = originalFile;
  681.     
  682.     
  683.     thePic = (PicHandle)NewHandle(sizeof(Picture));
  684.  
  685.     result = GetEOF(originalFile,&myEOF);
  686.     if (result != noErr) goto done;
  687.  
  688.     result = SetFPos(originalFile,fsFromStart,512);    /*skip header*/
  689.     if (result != noErr) goto done;
  690.  
  691.     longCount = sizeof(Picture);
  692.     result = FSRead(originalFile,&longCount,(Ptr)*thePic);
  693.     if (result != noErr) goto done;
  694.     
  695.     BlockMove(&(*thePic)->picFrame, &destRect, sizeof(Rect));
  696.     BlockMove(&destRect, &(Header.srcRect), sizeof(Rect));
  697.  
  698.     Header.version = -2;
  699.     Header.reserved1 = 0;
  700.     Header.reserved2 = 0;
  701.     Header.hRes = hRes;
  702.     Header.vRes = vRes;
  703.  
  704.     OutPict=OpenCPicture(&Header);
  705.     savedprocs = (CQDProcsPtr) qd.thePort->grafProcs;
  706.     
  707.         SetStdCProcs(&cprocs);
  708. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  709.         cprocs.getPicProc = GetPicUPP;
  710. #else
  711. #    ifndef THINK_C
  712.         cprocs.getPicProc = GetPICTData;
  713. #    else
  714.         cprocs.getPicProc = (Ptr)GetPICTData;
  715. #    endif
  716. #endif
  717.         qd.thePort->grafProcs = (QDProcsPtr) &cprocs;
  718.         
  719.  
  720.         DrawPicture( thePic, &destRect);
  721.         
  722.     
  723.     qd.thePort->grafProcs = (QDProcsPtr) savedprocs;
  724.     ClosePicture();
  725. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  726.     DisposeRoutineDescriptor(GetPicUPP);
  727. #endif
  728.     
  729.     if (EmptyRect(&(*OutPict)->picFrame))
  730.     {
  731.         SysBeep(1);
  732.         result = 1;
  733.     }
  734.                 
  735. done:
  736.     FSClose(originalFile);
  737.  
  738.     if(thePic)
  739.         DisposHandle((Handle)thePic);
  740.     thePic=nil;
  741.     
  742.     if (result!=noErr)
  743.     {    
  744.         if(OutPict)
  745.             DisposHandle((Handle)OutPict);
  746.         OutPict=nil;
  747.     }
  748.     SetPort((GrafPtr)savePort);
  749.     return(OutPict);
  750. }
  751.  
  752.  
  753. /*replacement for the QuickDraw bottleneck routine*/
  754.  
  755. pascal void GetPICTData ( Ptr dataPtr, short byteCount)
  756. {
  757.     OSErr     err;
  758.     long     longCount;
  759.  
  760.     longCount = byteCount;
  761.     err = FSRead(globalRef,&longCount,dataPtr);
  762.         /*can't check for an error because we don't know how to handle it*/
  763. }
  764.  
  765.  
  766. /************************************************************************************
  767.  
  768.     bottle neck proc to extract data from quicktime pict
  769.     
  770. *************************************************************************************/
  771.  
  772.  
  773. pascal void
  774. StdPixExtract(PixMap *src,Rect *srcRect,MatrixRecord matrix,short mode,RgnHandle mask,PixMap *matte,
  775.     Rect *matteRect,short flags) 
  776. {
  777. #pragma    unused(srcRect,matrix,matte,matteRect,flags,mode,mask)
  778.  
  779.     ICMDataProcRecord dataProc;
  780.     ICMProgressProcRecord progressProc;
  781.  
  782. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  783.     ICMDataUPP dataProcUPP;
  784.     ICMProgressUPP progressProcUPP;
  785. #endif
  786.  
  787.     ImageDescriptionHandle    idh;
  788.     long buffSize;
  789.     Ptr    data;
  790.     
  791.     long        lb,l;
  792.     short        i,m;
  793.     char         *buf,*abuf=nil,tbuf[32];
  794.  
  795.     
  796.     /************************************************************
  797.     
  798.      first check to see if it's a compressed pict opcode  
  799.      
  800.     ************************************************************/
  801.     
  802.     if ( GetCompressedPixMapInfo(src,&idh,&data,&buffSize,
  803.         &dataProc,
  804.         &progressProc
  805.         ) == 0 )
  806.     {
  807. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  808.         dataProcUPP = NewICMDataProc( &dataProc );
  809.         progressProcUPP = NewICMProgressProc ( &progressProc );
  810. #endif
  811.  
  812.     
  813.         /*******************************
  814.         
  815.          verify compression type 
  816.          
  817.          ********************************/
  818.         
  819.         
  820.         if (  (*idh)->cType != 'jpeg' ) {
  821.             extractionErr = paramErr;        // we only wanted jpeg
  822.             return;
  823.         }
  824.  
  825.  
  826.         l = (*idh)->dataSize;
  827.     
  828.  
  829.         /********************************
  830.         
  831.            make a JFIF header opcode in case the data doesn't have one -
  832.            QT JPEG always includes one but other JPEG compressors may not 
  833.            
  834.         ********************************/
  835.           
  836.     
  837.         {
  838.             buf = tbuf;
  839.             m = 0;
  840.             buf[m++] = MARKER_PREFIX;                // marker prefix
  841.             buf[m++] = MARKER_APP0;                // APP0 marker
  842.             buf[m++] = 0;                    // size word ( filled in later )
  843.             buf[m++] = 0;
  844.             buf[m++] = 'J';                    // tag 5 bytes
  845.             buf[m++] = 'F';
  846.             buf[m++] = 'I';
  847.             buf[m++] = 'F';
  848.             buf[m++] = 0;        
  849.             buf[m++] = 1;                    // version word
  850.             buf[m++] = 1;
  851.             buf[m++] = 1;                    // specify dpi
  852.             buf[m++] = (*idh)->hRes>>24;    // hres word
  853.             buf[m++] = (*idh)->hRes>>16;
  854.             buf[m++] = (*idh)->vRes>>24;    // vres word
  855.             buf[m++] = (*idh)->vRes>>16;
  856.             buf[m++] = 0;                    // thumbnail x 
  857.             buf[m++] = 0;                    // thumbnail y 
  858.         }
  859.         buf[2] = (m-2)>>8;                    // fill in size
  860.         buf[3] = (m-2);
  861.         i = 0;
  862.         
  863.         /********************************
  864.         
  865.         Scan the JPEG data till we get to the start of image marker.
  866.         
  867.         ********************************/
  868.         
  869.         
  870.         while ( data[i] == (char)MARKER_PREFIX ) {
  871.             if ( i++ > 1024 ) {
  872.                 extractionErr = -1;
  873.                 if ( abuf )
  874.                     DisposPtr(abuf);
  875.                 return;
  876.             }
  877.         }
  878.         if ( data[i++] != (char)MARKER_SOI ) { 
  879.             extractionErr = -1;
  880.             if ( abuf )
  881.                 DisposPtr(abuf);
  882.             return;
  883.         }
  884.         
  885.         /*******************************
  886.         
  887.         Write out all the data up to and including the start of image marker
  888.         
  889.         *******************************/
  890.         
  891.         lb = i;
  892.         if ( dataProc.dataProc ) {
  893.             if ( extractionErr = 
  894. #if GENERATINGCFM
  895.     CallICMDataProc( dataProcUPP,&data,lb,dataProc.dataRefCon )
  896. #else
  897.     dataProc.dataProc(&data,lb,dataProc.dataRefCon)
  898. #endif
  899.             )
  900.                 return;
  901.         }
  902.         if ( extractionErr = FSWrite(extractionFile,&lb,data) )  {
  903.             if ( abuf )
  904.                 DisposPtr(abuf);
  905.             return;
  906.         }
  907.         
  908.         /*******************************
  909.         
  910.         Check to see if there is a JFIF marker in the data already
  911.         
  912.         *******************************/
  913.     
  914.         
  915.         if ( data[i] == (char)MARKER_PREFIX &&  data[i+1] == (char)MARKER_APP0 ) {    // already have JFIF marker in stream
  916.             data += i;
  917.             l -= i;
  918.             goto no_jfif_marker;
  919.         } else {
  920.             data += i;
  921.             l -= i;
  922.         }
  923.     
  924.         lb = m;
  925.         if ( extractionErr = FSWrite(extractionFile,&lb,buf))  {
  926.             if ( abuf )
  927.                 DisposPtr(abuf);
  928.             return;
  929.         }
  930. no_jfif_marker:
  931.         if ( abuf )
  932.             DisposPtr(abuf);
  933.     
  934.         /*******************************
  935.         
  936.         Read the rest of the JPEG data and write it into the output file.
  937.         
  938.         *******************************/
  939.     
  940.     
  941.         if (  dataProc.dataProc ) {
  942.             lb = buffSize;
  943.             while ( l > buffSize ) {
  944.                 if ( extractionErr =
  945. #if GENERATINGCFM
  946.     CallICMDataProc( dataProcUPP,&data,lb,dataProc.dataRefCon )
  947. #else
  948.     dataProc.dataProc(&data,lb,dataProc.dataRefCon)
  949. #endif
  950.                 )  {
  951.                     return;
  952.                 }
  953.                 if ( extractionErr = FSWrite(extractionFile,&lb,data)) {
  954.                     return;
  955.                 }
  956.                 data += lb;
  957.                 l -= lb;
  958.             }
  959.             if ( extractionErr = 
  960. #if GENERATINGCFM
  961.     CallICMDataProc( dataProcUPP,&data,l,dataProc.dataRefCon )
  962. #else
  963.     dataProc.dataProc(&data,l,dataProc.dataRefCon)
  964. #endif
  965.             ) {
  966.                 return;
  967.             }
  968.             if ( extractionErr = FSWrite(extractionFile,&l,data)) {
  969.                 return;
  970.             }
  971.         } else {
  972.             if ( extractionErr = FSWrite(extractionFile,&l,data))
  973.                 return;
  974.         }
  975.     
  976.         
  977.  
  978.     } else {
  979.     
  980.         /*******************************
  981.         
  982.         Not compressed data - return error.
  983.         
  984.         *******************************/
  985.     
  986.  
  987.         extractionErr = paramErr;
  988.     }
  989. }
  990.  
  991.  
  992.